module com {
	export class ProtoManager {
		private static _instance: ProtoManager;

		private protos: any;

		public constructor() {
		}

		public static getInstance(): ProtoManager {
			if (this._instance == null) {
				this._instance = new ProtoManager();
			}

			return this._instance;
		}

		/**初始化所有的proto文件 */
		public init(msg = null): void {
			// let str = RES.getRes("pack_json");
			// console.warn(str);
			this.protos = RES.getRes("pack_json");
			console.warn(this.protos);
		}

		/**解码 */
		public decode(str: string): BaseProto {
			let byte_arr = new egret.ByteArray();
			byte_arr.buffer = Base64Util.StringToArrayBuffer(str);

			let code = byte_arr.readShort();
			console.log('code:', code);
			let head = byte_arr.readShort();
			let head_str = this.getHeadStr(head);
			console.log('head:', head_str);
			let body_name = byte_arr.readUTF();
			console.log('body_name:', body_name);

			let origin_obj = this.protos[head_str][body_name];
			let body_len = 0;
			for (let key in origin_obj) {
				body_len++;
			}
			let body = {};

			while (body_len > 0) {
				body_len--;
				let type = byte_arr.readShort();
				console.log('decode -- type:', type);
				let len = 0;
				let key = '';
				let value;

				switch (type) {
					case this.protos.type.number:
						key = byte_arr.readUTF();
						value = byte_arr.readInt();
						break;
					case this.protos.type.string:
						key = byte_arr.readUTF();
						value = byte_arr.readUTF();
						break;
					case this.protos.type.boolean:
						key = byte_arr.readUTF();
						value = byte_arr.readShort();
						break;
					case this.protos.type.arr_number:
						len = byte_arr.readShort();
						key = byte_arr.readUTF();
						value = [];
						for (let i = 0; i < len; i++) {
							let num = byte_arr.readInt();
							value.push(num);
						}
						break;
					case this.protos.type.arr_string:
						len = byte_arr.readShort();
						key = byte_arr.readUTF();
						value = [];
						for (let i = 0; i < len; i++) {
							let s = byte_arr.readUTF();
							value.push(s);
						}
						break;
				}
				body[key] = value;
			}
			let result = new BaseProto();
			result.code = code;
			result.head = head;
			result.body_name = body_name;
			result.body = body;
			return result;
		}
		/**
		 * 获取headstr
		 * @param head --> 必传参数，默认值是为了显示类型
		 */
		public getHeadStr(head = 0) {
			let head_enum = this.protos.head;
			let head_str = "";

			switch (head) {
				case head_enum.register:
					head_str = 'register';
					break;
				case head_enum.login:
					head_str = 'login';
					break;
				case head_enum.pay:
					head_str = 'pay';
					break;
				case head_enum.app:
					head_str = 'app';
					break;
				case head_enum.popgame:
					head_str = 'popgame';
					break;
				case head_enum.defense:
					head_str = 'defense';
					break;
			}

			return head_str;
		}
		/**编码 */
		public encode(proto: BaseProto): string {
			let byte_arr = new egret.ByteArray();

			byte_arr.writeShort(proto.code);
			byte_arr.writeShort(proto.head);
			byte_arr.writeUTF(proto.body_name);

			for (let key in proto.body) {
				let value = proto.body[key];
				let type = 0;

				if (typeof value === 'boolean') {
					type = ProtoType.boolean;
					byte_arr.writeShort(type);
					byte_arr.writeUTF(key);
					byte_arr.writeShort(value == true ? 1 : 0);
				}
				else if (typeof value === 'number') {
					type = ProtoType.number;
					byte_arr.writeShort(type);
					byte_arr.writeUTF(key);
					// value_buff = Buffer.alloc(4);
					// value_buff.writeInt32LE(value);
					byte_arr.writeInt(value);
				}
				else if (typeof value === 'string') {
					type = ProtoType.string;
					byte_arr.writeShort(type);
					byte_arr.writeUTF(key);

					byte_arr.writeUTF(value);
				}
				else if (Array.isArray(value)) {
					if (!value[0]) {//不允许空数组
						throw "不允许空数组.....";
						// return "";
					}
					else {
						if (typeof value[0] === 'number') {
							type = ProtoType.arr_number;
						}
						else if (typeof value[0] === 'string') {
							type = ProtoType.arr_string;
						}
						byte_arr.writeShort(value.length);
						byte_arr.writeShort(type);
						byte_arr.writeUTF(key);
						// let buff_list = [];
						for (let i = 0; i < value.length; i++) {
							let buff;
							if (typeof value[i] === 'number') {
								// console.log('encode -- arr_number:', value[i]);
								byte_arr.writeInt(value[i]);
							}
							else if (typeof value[i] === 'string') {
								// console.log('encode -- arr_string:', value[i]);
								byte_arr.writeUTF(value[i]);
							}

							// buff_list.push(buff);
						}
						// value_buff = Buffer.concat(buff_list);
					}
				}
			}

			let str = Base64Util.ArrayBufferToString(byte_arr.buffer);
			return str;
		}
	}
}